package cn.zvo.websocket.framework.springboot.netty;

import java.util.HashMap;
import java.util.Map;
import cn.zvo.websocket.framework.springboot.enums.MessageTypeEnum;
import cn.zvo.websocket.framework.springboot.util.MessageStorageUtil;
import cn.zvo.websocket.framework.springboot.util.MessageUtil;
import cn.zvo.websocket.framework.springboot.util.SocketUtil;
import cn.zvo.websocket.framework.springboot.vo.MessageReceiveVO;
import cn.zvo.websocket.framework.springboot.vo.bean.Message;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;

/**
 * 自定义助手类
 * @author 管雷鸣
 *
 */
public class NettyHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {//TextWebSocketFrame是netty用于处理websocket发来的文本对象
	//所有正在连接的channel都会存在这里面，所以也可以间接代表在线的客户端
	public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
	// key  Channel.id ， 
	public static Map<String, Channel> channelMap;
	static{
		channelMap = new HashMap<String, Channel>();
	}
	

	/**
     * 客户端创建的时候触发，当客户端连接上服务端之后，就可以获取该channel，然后放到channelGroup中进行统一管理	
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        channelGroup.add(ctx.channel());
//        MessagePluginManage.online(ctx.channel());
    }
    
    /**
     * 关闭连接,客户端销毁的时候触发
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
//    	MessagePluginManage.offline(ctx.channel());
    	channelGroup.remove(ctx.channel());
    }

    //出现异常
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
    }
    
    
    /**
     * 接收到客户端发来的消息进行处理
     */
	@Override
	protected void messageReceived(ChannelHandlerContext ctx, TextWebSocketFrame textWebSocketFrame) throws Exception {
		//客户端传递过来的消息
		String content = textWebSocketFrame.text();
		MessageReceiveVO msg = MessageUtil.receiveStringToJson(content);
		
		if(msg.getType().equalsIgnoreCase(MessageTypeEnum.HEARTBEAT.name)){
			//心跳，回应
			SocketUtil.sendHeartbeatMessageReply(ctx.channel());
			return;
		}
		
		MessageStorageUtil.push(msg); //消息进行持久化存储
//		ConsoleUtil.log("messageReceived: "+content);
		
		//判断此条是否是刚打开连接成功自动发送的。如果是，那么进行绑定通道跟用户
		if(msg.getType().equalsIgnoreCase(MessageTypeEnum.CONNECT.name)){
			//open时推送来的消息
			
			String token = msg.getToken(); //获取该用户的token
			
			/*
			 * 根据token来判断当前是哪个用户
			 * 取到用户的唯一标识
			 * 
			 */
			String chatid = token;	//这里先暂时用token替代
			SocketUtil.bind(chatid, ctx.channel());		//将用户标识跟socket通道绑定
			
			
			/**** 模拟发送一个消息回复 ****/
			//创建要发送出去的消息
			Message message = new Message();
			message.setSendId(msg.getReceiveId());
			message.setReceiveId(msg.getSendId());
			message.setType(MessageTypeEnum.MSG.name);
			message.setText("我知道你是谁了");
			//将消息回复给客户端
			SocketUtil.sendMessage(ctx.channel(), message);	
			
			return;
		}else if(msg.getType().equalsIgnoreCase(MessageTypeEnum.MSG.name)){
			//正常沟通推送过来的消息、扩展消息，进行对话
			
			
			/**** 模拟发送一个消息回复 ****/
			//创建要发送出去的消息
			Message message = new Message();
			message.setSendId(msg.getReceiveId());
			message.setReceiveId(msg.getSendId());
			message.setType(MessageTypeEnum.MSG.name);
			message.setText("收到你的信息了-"+msg.getText());
			//将消息回复给客户端
			SocketUtil.sendMessage(ctx.channel(), message);
			
			return;
		}
	}
}